package scene.composants.liaisons;

import java.awt.*;

import scene.composants.IDessinableManipulable;
import scene.composants.elements.Ligne;
import scene.composants.elements.PointExtremite;

/**
 * Represente une laision avec un composant et un point de destination deplacable
 * 
 * @author Delmas Gabriel
 */
public class RepresentationLienNote implements IDessinableManipulable
{
	protected IDessinableManipulable cPrincipale;
	protected Point cSource;
	protected Ligne lien;
	protected Point pSource;
	
	//Rectangle rect;
	Ligne l[];
	protected PointExtremite pext_source, pext_destination;
	protected boolean estSelectionner;
	protected boolean estTransferer;
	protected String extremiteSelectionner;
	//Permet de garder le centrage de la figure lors du deplacement
	private Dimension xyespace;

	
	public RepresentationLienNote(IDessinableManipulable cPrincipale, Point cSource)
	{
		this.cPrincipale=cPrincipale;
		this.cSource=cSource;
		initialiser();		
	}
	private void initialiser()
	{
		this.l=new Ligne[4];
		
		this.estSelectionner=false;
		this.estTransferer=false;
		this.extremiteSelectionner="";
		xyespace = new Dimension(0,0);
		
		pext_source=new PointExtremite(0,0);
		pext_destination=new PointExtremite(0,0);
		pSource=new Point(0,0);
	}	
	public void CalculGraphique()
	{	
		Point pDeb, pFin, p;
		pDeb = new Point();
		pFin = new Point();
		

		lien = new Ligne(cPrincipale.getPositionCentre(),this.cSource);
			
		pDeb.setLocation(cPrincipale.getRectangle().x, cPrincipale.getRectangle().y);
		pFin.setLocation(cPrincipale.getRectangle().x, cPrincipale.getRectangle().y+cPrincipale.getRectangle().height);	
		l[0]=new Ligne(pDeb,pFin);
		pDeb.setLocation(cPrincipale.getRectangle().x, cPrincipale.getRectangle().y);
		pFin.setLocation(cPrincipale.getRectangle().x+cPrincipale.getRectangle().width, cPrincipale.getRectangle().y);	
		l[1]=new Ligne(pDeb,pFin);
		pDeb.setLocation(cPrincipale.getRectangle().x, cPrincipale.getRectangle().y+cPrincipale.getRectangle().height);
		pFin.setLocation(cPrincipale.getRectangle().x+cPrincipale.getRectangle().width, cPrincipale.getRectangle().y+cPrincipale.getRectangle().height);	
		l[2]=new Ligne(pDeb,pFin);
		pDeb.setLocation(cPrincipale.getRectangle().x+cPrincipale.getRectangle().width, cPrincipale.getRectangle().y);
		pFin.setLocation(cPrincipale.getRectangle().x+cPrincipale.getRectangle().width, cPrincipale.getRectangle().y+cPrincipale.getRectangle().height);	
		l[3]=new Ligne(pDeb,pFin);
		
		p=null;
		
		for(int i=0;i<4;i++)
		{
			Point pTemp=IntersectionLignes(cPrincipale.getPositionCentre(),cSource,l[i].getPosition(),l[i].getPDestination());
			if(pTemp!=null)
			{
				p=pTemp;
			}
		}
		//Si les figures se chevauche
		if(p!=null)
			lien.setPSource(p);

		
		lien.setPDestination(cSource);
		
		if(cPrincipale.getRectangle().contains(cSource))
			lien=null;
		
		if(lien!=null)
			if(lien.getPSource().equals(lien.getPDestination()))
				lien=null;
		
		Point pPos;
		
		if(lien!=null)
		{
			//On calcule les points des extremites
			pPos=new Point(lien.getPSource().x,lien.getPSource().y);
			pext_source.setPosition(pPos);
			pPos=new Point(lien.getPDestination().x,lien.getPDestination().y);
			pext_destination.setPosition(pPos);
			pSource.setLocation(lien.getPosition().x, lien.getPosition().y);
		}
	}

	 Point IntersectionLignes(Point p1,Point p2,Point p3,Point p4)
	 {  
	   float xD1,yD1,xD2,yD2,xD3,yD3;  
	   double dot,deg,len1,len2;  
	   double segmentLen1,segmentLen2;  
	   float ua,ub,div;  
	   
	   //Calcul des differences  
	   xD1=p2.x-p1.x;  
	   xD2=p4.x-p3.x;  
	   yD1=p2.y-p1.y;  
	   yD2=p4.y-p3.y;  
	   xD3=p1.x-p3.x;  
	   yD3=p1.y-p3.y;    
	   
	   //Calcul des longeurs des deux lignes  
	   len1=Math.sqrt(xD1*xD1+yD1*yD1);  
	   len2=Math.sqrt(xD2*xD2+yD2*yD2);
	   
	   //Calcul angle entre les deux lignes  
	   dot=(xD1*xD2+yD1*yD2); 
	   deg=dot/(len1*len2);  
	   
	   //Si abs(angle)==1 alors les lignes sont parallele
	   //donc pas d'intersection 
	   if(Math.abs(deg)==1) return null;  
	   
	   //Trouve l'intersection pt entre deux lignes 
	   Point pt=new Point(0,0);  
	   div=yD2*xD1-xD2*yD1;  
	   ua=(xD2*yD3-yD2*xD3)/div;  
	   ub=(xD1*yD3-yD1*xD3)/div;  
	   pt.x=Float.valueOf(p1.x+ua*xD1).intValue();
	   pt.y=Float.valueOf(p1.y+ua*yD1).intValue();  
	   
	   //Calcul la longeur combine des deux segments
	   //entre Pt-p1 et Pt-p2  
	   xD1=pt.x-p1.x;  
	   xD2=pt.x-p2.x;  
	   yD1=pt.y-p1.y;  
	   yD2=pt.y-p2.y;  
	   segmentLen1=Math.sqrt(xD1*xD1+yD1*yD1)+Math.sqrt(xD2*xD2+yD2*yD2);  
	   
	   //Calcul la longeur combine des deux segments
	   // entre Pt-p3 et Pt-p4  
	   xD1=pt.x-p3.x;  
	   xD2=pt.x-p4.x;  
	   yD1=pt.y-p3.y;  
	   yD2=pt.y-p4.y;  
	   segmentLen2=Math.sqrt(xD1*xD1+yD1*yD1)+Math.sqrt(xD2*xD2+yD2*yD2);
	   
	    
	   
	   //Si le point n'est pas sur la ligne return null  
	   if(Math.abs(len1-segmentLen1)>0.1 || Math.abs(len2-segmentLen2)>0.1)  
	     return null;
	   
	   // return le point d'intersection valide 
	   return pt;  
	 }
	
	
	public void dessiner(Graphics2D g2d)
	{
		
		Composite originalComposite = g2d.getComposite();
		
		if(cPrincipale.getTransfere())
		{
			g2d.setComposite(makeComposite(0.5F));
		}
		
		Color couleur=g2d.getColor();
		g2d.setColor(Color.black);
		

		CalculGraphique();
		
		if(lien!=null)
		{
			lien.dessiner(g2d);
		}
		
		
		/*
		g2d.setColor(Color.red);
		l[0].dessiner(g2d);
		l[1].dessiner(g2d);
		l[2].dessiner(g2d);
		l[3].dessiner(g2d);
		g2d.setColor(Color.black);
		*/
		//Trace des extremites
		if(estSelectionner && lien!=null)
		{
			pext_source.dessiner(g2d);
			pext_destination.dessiner(g2d);
		}
		
		
		g2d.setColor(couleur);
		g2d.setComposite(originalComposite);
	}
	
	
	protected AlphaComposite makeComposite(float alpha)
	{
		int type = AlphaComposite.SRC_OVER;
		return(AlphaComposite.getInstance(type, alpha));
	}

	public void deplacerExtremite(Point p_new)
	{
		//On deplace qu'une extremite
		if(extremiteSelectionner=="haut_droite")
		{
			cSource=p_new;		
		}
	}

	public void setExtremiteSelectionnee(String nom_extremite){extremiteSelectionner=nom_extremite;}
	public String getExtremiteSelectionnee(){return extremiteSelectionner;}

	public Point getPosition()
	{
		return pSource;
	}


	public Rectangle getRectangle()
	{
		return null;
	}
	public Dimension getDimension()
	{
		if(lien!=null)
			return new Dimension(this.lien.getPSource().x-this.lien.getPDestination().x,5);
		else 
			return new Dimension(1,1);
	}
	public Dimension getXYEspace()
	{
		return this.xyespace;
	}
	public void setXYEspace(Dimension xyespace)
	{
		this.xyespace.width=xyespace.width;
		this.xyespace.height=xyespace.height;
		
	}

	public boolean intersectionExtremite(Point p)
	{
		if(pext_source.Clique(p))
		{
			extremiteSelectionner="haut_gauche";
			pext_source.setSelection(true);
		}
		else if(pext_destination.Clique(p))
		{
			extremiteSelectionner="haut_droite";
			pext_destination.setSelection(true);
		}
		return pext_source.getSelection()||pext_destination.getSelection();
	}

	public void relacherExtremites()
	{
		pext_source.setSelection(false);
		pext_destination.setSelection(false);
	}


	public void setEstTransfere(boolean transferer){estTransferer=transferer;}
	public boolean getTransfere(){return estTransferer;}
	
	public void setEstSelectionner(boolean select){this.estSelectionner=select;}
	public boolean getEstSelectionner(){return this.estSelectionner;}

	public void setPosition(Point p)
	{
		if(lien!=null)
			lien.setPSource(p);
		CalculGraphique();
		
	}

	public boolean intersection(Point p)
	{
		if(lien!=null)
		{
			if(IntersectionLignes(lien.getPSource(),lien.getPDestination(),new Point(p.x-5,p.y-5),new Point(p.x+5,p.y+5))==null)
			return false;
		else
			return true;
		}
		else return false;
	}

	public boolean intersection(Rectangle r)
	{
		if(lien!=null)
		{
			Point pTemp=null;
			Point pVerif=null;
			Point pDeb, pFin;
			pDeb=new Point();
			pFin=new Point();
			
			pDeb.setLocation(r.getLocation().x, r.getLocation().y);
			pFin.setLocation(r.getLocation().x, r.getLocation().y+r.height);	
			pTemp=IntersectionLignes(lien.getPSource(),lien.getPDestination(),pDeb,pFin);
			if(pTemp!=null)
				pVerif=pTemp;
			pDeb.setLocation(r.getLocation().x, r.getLocation().y);
			pFin.setLocation(r.getLocation().x+r.width, r.getLocation().y);	
			pTemp=IntersectionLignes(lien.getPSource(),lien.getPDestination(),pDeb,pFin);
			if(pTemp!=null)
				pVerif=pTemp;
			pDeb.setLocation(r.getLocation().x, r.getLocation().y+r.height);
			pFin.setLocation(r.getLocation().x+r.width, r.getLocation().y+r.height);	
			pTemp=IntersectionLignes(lien.getPSource(),lien.getPDestination(),pDeb,pFin);
			if(pTemp!=null)
				pVerif=pTemp;
			pDeb.setLocation(r.getLocation().x+r.width, r.getLocation().y);
			pFin.setLocation(r.getLocation().x+r.width, r.getLocation().y+r.height);	
	
			pTemp=IntersectionLignes(lien.getPSource(),lien.getPDestination(),pDeb,pFin);
			if(pTemp!=null)
				pVerif=pTemp;
			
			if(r.contains(lien.getPSource())&&r.contains(lien.getPDestination()))
				return true;
		
			if(pVerif==null)
				return false;
			else return true;
		}
		else return false;
	}

	public boolean dependanceHeritage(IDessinableManipulable figure)
	{
		if(figure.equals((IDessinableManipulable) this.cPrincipale))
			return true;
		return false;
	}


	public Point getPositionCentre()
	{
		return null;
	}
	public void actionDoubleClique()
	{
		//ENV.FRAME.getControleur().modifierNote(this);
	}
	public void actionMenuContextuel(Point p)
	{
		//ENV.FRAME.getControleur().afficherMenuContextuel(this, p);
	}
/*
	public void actionMenuContextuel(Component comp, SceneEditeur scene, Point p)
	{
		popupEdition = new HeritageJPopupMenu();
		popupEdition.show(comp, p.x, p.y);
		popupEdition.setVisible(true);
	
	}

	public void cacherMenuContextuel()
	{
		if(popupEdition!=null)
			popupEdition.setVisible(false);
		
	}
	//Redefinition de IDessinableManipulable
	public void actionDoubleClique()
	{
		
	}
	public void actionMenuContextuel(Point p)
	{

		
	}*/
	public boolean dependanceAgregation(IDessinableManipulable figure)
	{
		return false;
	}
}
